#ifndef __2BWTSEARCH_H__
#define __2BWTSEARCH_H__
#include "Index.h"
#include "Query.h"
#include <mian_util.h>
#include "buffer.h"


void BWT2GBWT(BWT *bwt, BWT **temp, unsigned int** d_occ = NULL);
void CudaFreeBWT(BWT *d_bwt);



uint64 BWTSearchStream(unsigned int * Queries, unsigned int queryNum, BWT *bwt, BWT *revbwt);

void createOccValueFile(BWT *bwt,char* fileName);

////////////////
void GPU2BWTInit(BWT** d_bwt, BWT** d_revbwt, 
				BWT* bwt, BWT* revbwt, 
				st_MemoryBuf** GPUMemBuf, const uint64 gpuBufSize);
				
uint64 GPU2BWTSearch(const unsigned int * d_Queries, unsigned int queryNum, 
					BWT *d_bwt, BWT *d_revbwt, 
					st_MemoryBuf* GPUMemBuf);

uint64 GPU2BWTSearchLimit(long* d_numAlign,
                        const unsigned int * h_Queries, unsigned int queryNum, 
                                        BWT *d_bwt, BWT *d_revbwt,
                                        st_MemoryBuf* GPUMemBuf, uint3* h_result, uint32* h_resultNum);

uint64 GPU2BWTSearchTwoStrandLimit(long* d_numAlign,
                                        const unsigned int* h_Queries, const unsigned int* h_revQueries,
                                        unsigned int queryNum,
                                        BWT *d_bwt, BWT *d_revbwt,
                                        st_MemoryBuf* GPUMemBuf, uint3* h_result, uint32* h_resultNum) ;


uint64 GPU2BWTSearch1Kernel(const unsigned int * h_Queries, unsigned int queryNum,
                BWT *d_bwt, BWT *d_revbwt,
                st_MemoryBuf* GPUMemBuf);

uint64 GPU2BWTSearch_noConcurent(const unsigned int * h_Queries, unsigned int queryNum,  
                BWT *d_bwt, BWT *d_revbwt, 
                st_MemoryBuf* GPUMemBuf);
 
uint64 GPU2BWTSearch_shareBuf(const unsigned int * h_Queries, unsigned int queryNum,
		BWT *d_bwt, BWT *d_revbwt,
		st_MemoryBuf* GPUMemBuf, uint3* h_result, uint32* h_resultNum);

unsigned int * SortQueriesBackward(unsigned int * Queries, unsigned int queryNum);
unsigned int * SortQueriesForward(unsigned int * Queries, unsigned int queryNum);
void sortSA(uint3* cpuSA, uint32 numSA);

void GPU2BWTInitIndex(BWT** d_bwt, BWT** d_revbwt,
                BWT* bwt, BWT* revbwt,
                st_MemoryBuf** GPUMemBuf, const uint64 gpuBufSize);

#endif
